package high.concurrent.interceptor;

import high.concurrent.enums.BizCodeEnum;
import high.concurrent.exception.BizException;
import high.concurrent.model.LoginUser;
import high.concurrent.utils.JWTTokenUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户信息的拦截器(通用)
 */
@Slf4j
public class UserInterceptor implements HandlerInterceptor {

    /**
     * threadLocal无需手动清空，因为底层Entry对ThreadLocal的引用是弱引用，会自动清空
     */
    public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();
    /**
     * 处理请求之前调用
     * @param request
     * @param response
     * @param handler
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        // 取得header的token
        String accessToken = request.getHeader("token");
        if(accessToken == null){
            // header不存在token，则去参数中再获取一次
            accessToken = request.getParameter("token");
        }

        if(StringUtils.isNotBlank(accessToken)){

            // 存在token则解密
            Claims claims = JWTTokenUtil.checkJWT(accessToken);
            if(claims != null){

                // 把token中payload的参数Claims对象中的用户信息注入到LoginUser类，供所有服务使用
                LoginUser loginUser = LoginUser.builder()
                        .id(Long.parseLong(claims.get("id").toString()))
                        .headImg((String) claims.get("head_img"))
                        .mail((String) claims.get("mail"))
                        .name((String) claims.get("name"))
                        .build();

                // 通过把Attribute拿取LoginUser用户信息作为参数传给接口, 接口那信息需要用request.getAttribute("loginUser");
//                request.setAttribute("loginUser", loginUser);

                // 通过threadLocal来进行传参
                threadLocal.set(loginUser);
                return true;
            }
        }

        // 如果token不存在 或 不正确，则直接返回给前端异常
        throw new BizException(BizCodeEnum.ACCOUNT_UNLOGIN);

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 链路用完后，就把threadLocal清理掉
        threadLocal.remove();
    }
}
